#pragma once
#ifndef __MESSAGE_H__
#define __MESSAGE_H__

#include <vector>
#include <memory>
#include <span>
#include <string.h>
#include <util/Endpoint.hpp>
#include <iostream>

enum class MessageType : uint32_t{
    REQUEST,
    RESPONSE,
    FORWARD
};

struct alignas(32) router_info{
    Endpoint from;
    Endpoint to;
    MessageType message_type;   // 三种消息： 请求（命令）  响应  转发
    size_t data_size;
};

// 三种消息： 请求  响应  转发  
// 第4种，  事件通知，  虚拟server  真实客户  虚拟客户  发送的通知
// 第5种   心跳包
struct message{
    message(size_t buffer_size = 10240):
        buffer(std::make_shared<std::vector<char>>(buffer_size))
    { }

    router_info& get_router_info(){
        return *reinterpret_cast<router_info*>(buffer->data());
    }

    void set_message_type(MessageType type){
        get_router_info().message_type = type;
    }

    void set_sender(Endpoint const& sender){
        get_router_info().from = sender;
    }

    void set_receiver(Endpoint const& receiver){
        get_router_info().to = receiver;
    }

    static std::pair<message,bool> read_message_from(int fd){
        message msg;
        bool is_valid = true;
        int n = msg.read_data(fd, 0, sizeof(router_info));
        if (n <= 0){
            is_valid = false;
            return std::make_pair(msg, is_valid);
        }
        n = msg.read_data(fd, sizeof(router_info), msg.get_router_info().data_size);
        if (n <= 0){
            is_valid = false;
        }
        return std::make_pair(msg, is_valid);
    }

    static void write_message_to(message msg, int fd){
        // 写进buffer里的已经是网络序
        msg.write_data(fd, 0, sizeof(router_info) + msg.get_router_info().data_size);
    }

    void* get_content_ptr(size_t offset){
        return buffer->data() + sizeof(router_info) + offset;
    }

    void set_content(size_t offset, void* ptr, size_t size){
        if (sizeof(router_info) + offset + size > buffer->size()){
            buffer->resize(sizeof(router_info) + offset + size);
        }
        memcpy(get_content_ptr(offset), ptr, size);
        get_router_info().data_size = std::max(offset + size, get_router_info().data_size);
    }

private:
    int read_data(int fd, size_t offset, size_t size)
    {
        int remains = size;
        void *buffer_data = buffer->data() + offset;
        while (remains != 0)
        {
            int read_n = read(fd, buffer_data + size - remains, remains);
            if (read_n == 0 || read_n == -1)
                return read_n;
            remains -= read_n;
        }
        return size;
    }

    int write_data(int fd, size_t offset, int size)
    {
        int remains = size;
        void *buffer_data = buffer->data() + offset;
        while (remains != 0)
        {
            int write_n = write(fd, buffer_data + size - remains, remains);
            if (write_n == -1)
                return write_n;
            remains -= write_n;
        }
        return size;
    }

protected:
    std::shared_ptr<std::vector<char>> buffer;
};

#endif // __MESSAGE_H__